package wshandler

import (
	"encoding/json"
	"fmt"

	. "starsine.cn/appTpl/cmn/defs"
	"starsine.cn/appTpl/cmn/logs"
	"starsine.cn/appTpl/svccenter/registry/restful/chan2svc"
	"starsine.cn/appTpl/svccenter/registry/restful/openapi"
	"starsine.cn/appTpl/svccenter/registry/restful/ws-server/wsserver"
	"starsine.cn/appTpl/svccenter/registry/svcmng"
	"starsine.cn/appTpl/svccenter/registry/svcmng/iservice"
)

func WsMsgHandler(conn *wsserver.WsServer, msg []byte) {
	head := openapi.WsRequestTpl{}
	err := json.Unmarshal(msg, &head)
	if err != nil {
		logs.Warnf("WsMsgHandler Unmarshal fail, err: %s", err)
		return
	}

	switch head.MsgHead.RequestType {
	case "ws-heartbeat", "svc-heartbeat":
		logs.Debugf("SvcHandler.WsMsgHandler get msg: %s", head.MsgHead.RequestType)
		svc, ok := chan2svc.GetSvcFromWsServer(conn)
		if !ok {
			logs.Warnf("WsMsgHandler %s from wsServer, but svc is not exist, drop it.", head.MsgHead.RequestType)
			return
		} else {
			svc.MsgHandler(msg)
		}

	case "svc-registry":
		logs.Debugf("SvcHandler.WsMsgHandler get svc-registry")
		svc := registryRequestHandle(conn, msg)
		if svc == nil {
			logs.Warnf("SvcHandler.WsMsgHandler registryRequestHandle fail")
			return
		} else {
			svc.Start(conn)
			chan2svc.AddC2SMap(conn, svc)
		}

	case "svc-unregistry":
		logs.Debugf("SvcHandler.WsMsgHandler get svc-unregistry")
		err := unregistryRequestHandle(conn, msg)
		if err == nil {
			logs.Warnf("SvcHandler.WsMsgHandler unregistryRequestHandle fail")
			return
		} else {
			if svc, ok := chan2svc.GetSvcFromWsServer(conn); ok {
				svc.End()
				chan2svc.DelC2SMap(svc)
			}
		}

	default:
		logs.Warnf("WsMsgHandler unknown request type: %s", head.MsgHead.RequestType)
	}
}

func registryRequestHandle(conn *wsserver.WsServer, msg []byte) iservice.IService {
	data := openapi.RegistryRequest{}

	err := json.Unmarshal(msg, &data)
	if err != nil {
		logs.Warnf("registryRequestHandle Unmarshal fail, err: %s", err)
		return nil
	}

	svc, err := svcmng.ServiceReg(data.Data.SvcType, data.Data.Name, data.Data.UserSpace, SvcData{
		RpcAddr: data.Data.Rpc,
	})
	if err != nil {
		logs.Warnf("svc(%+v) register fail, err: %s", data, err)
		conn.SendMessage(&openapi.RegistryResponse{
			MsgHead: openapi.WsHead{
				InstanceID:  "sc-instance-id",
				ResOrReq:    "res",
				RequestType: "svc-registry",
				SerialNum:   data.MsgHead.SerialNum,
				Message:     fmt.Sprintf("registry fail, err: %s", err),
				Status:      "fail",
			},
		})
		return nil
	} else {
		conn.SendMessage(&openapi.RegistryResponse{
			MsgHead: openapi.WsHead{
				InstanceID:  "sc-instance-id",
				ResOrReq:    "res",
				RequestType: "svc-registry",
				SerialNum:   data.MsgHead.SerialNum,
				Message:     fmt.Sprintf("registry ok, instance id: %s", svc.GetInstanceID()),
				Status:      "ok",
			},
			Data: openapi.RegistryInfo{
				InstanceID: svc.GetInstanceID(),
			},
		})
		return svc
	}
}

func unregistryRequestHandle(conn *wsserver.WsServer, msg []byte) error {
	data := openapi.RegistryRequest{}

	err := json.Unmarshal(msg, &data)
	if err != nil {
		logs.Warnf("unregistryRequestHandle Unmarshal fail, err: %s", err)
		return fmt.Errorf("unregistryRequestHandle Unmarshal fail, err: %s", err)
	}

	err = svcmng.ServiceUnreg(data.Data.SvcType, data.Data.Name, data.Data.UserSpace)
	if err != nil {
		logs.Warnf("svc(%+v) unregister fail, err: %s", data, err)
		conn.SendMessage(&openapi.RegistryResponse{
			MsgHead: openapi.WsHead{
				InstanceID:  "sc-instance-id",
				ResOrReq:    "res",
				RequestType: "svc-unregistry",
				SerialNum:   data.MsgHead.SerialNum,
				Message:     fmt.Sprintf("unregister fail, err: %s", err),
				Status:      "fail",
			},
		})
		return fmt.Errorf("svc(%+v) unregister fail, err: %s", data, err)
	} else {
		conn.SendMessage(&openapi.RegistryResponse{
			MsgHead: openapi.WsHead{
				InstanceID:  "sc-instance-id",
				ResOrReq:    "res",
				RequestType: "svc-unregistry",
				SerialNum:   data.MsgHead.SerialNum,
				Message:     fmt.Sprintf("unregister ok"),
				Status:      "ok",
			},
		})
		return nil
	}
}
